package org.luosl.webmagicx.listeners

import java.text.DecimalFormat
import java.util.Date
import java.util.concurrent.atomic.AtomicLong

import org.luosl.webmagicx.Utils.{DateUtils, Logging}
import org.luosl.webmagicx.conf.SpiderConf
import play.api.libs.json.{JsObject, Json}
import us.codecraft.webmagic.scheduler.MonitorableScheduler
import us.codecraft.webmagic.{Request, Spider, SpiderListener}


/**
  * 通用的爬虫监听
  * Created by luosl on 2017/12/6.
  */
class GeneralSpiderListener(spider:Spider, sc:SpiderConf) extends Logging with SpiderListener{

  private val startTime:Date = new Date()

  private val successCount:AtomicLong = new AtomicLong()

  private val errorCount:AtomicLong = new AtomicLong()

  override def onSuccess(request: Request): Unit = successCount.getAndIncrement()

  override def onError(request: Request): Unit = errorCount.getAndIncrement()

  def createJsonMsg(): JsObject ={
    val (totalRequestsCount, leftRequestsCount) = totalOrLeftRequestCount()
    Json.obj(
      "id" -> sc.id,
      "desc" -> sc.desc,
      "startTime" -> DateUtils.dateFormat(startTime),
      "runTime" -> runTime(),
      "taskType" -> sc.taskType,
      "status" -> spider.getStatus.toString,
      "threadNum" -> sc.attribute.threadNum,
      "configPath" -> sc.path,
      "totalRequestsCount" -> totalRequestsCount,
      "leftRequestsCount" -> leftRequestsCount,
      "successCount" -> successCount.get(),
      "errorCount" -> errorCount.get()
    )
  }

  /**
    * 获取当前队列中Url个数
    * @return
    */
  private def totalOrLeftRequestCount():(Int, Int) ={
    spider.getScheduler match {
      case ms:MonitorableScheduler =>
        (ms.getTotalRequestsCount(spider),ms.getLeftRequestsCount(spider))
      case _ => (-1, -1)
    }
  }

  /**
    * 获取运行时间
    * @return
    */
  def runTime(): String = {
    val timeDiff:Double = (new Date().getTime - startTime.getTime).toDouble
    val hf:Int = 1000 * 60 * 60
    val mf:Int = 1000 * 60
    if(timeDiff / hf > 1){
      s"${numFormat(timeDiff / hf)} h"
    }else if(timeDiff / mf > 1){
      s"${numFormat(timeDiff / mf)} m"
    }else{
      s"${numFormat(timeDiff / 1000)} s"
    }
  }

  def numFormat(d:Double): String ={
    val df:DecimalFormat = new DecimalFormat("#.00")
    df.format(d)
  }

}

